home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / Kibitz / Offscreen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  11.7 KB  |  382 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        offscreen.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1991-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __ERRORS__
  21. #include "Errors.h"
  22. #endif
  23.  
  24. #ifndef __GWLAYERS__
  25. #include <GWLayers.h>
  26. #endif
  27.  
  28. #ifndef __RESOURCES__
  29. #include <Resources.h>
  30. #endif
  31.  
  32. #ifndef __UTILITIES__
  33. #include <Utilities.h>
  34. #endif
  35.  
  36.  
  37.  
  38. static short        gDepth, gPiece;
  39. static CTabHandle    gCtab;
  40. static Rect            gPieceRect;
  41. static RgnHandle    gColorRgn, gTestRgn;
  42.  
  43.  
  44.  
  45. /*****************************************************************************/
  46.  
  47.  
  48.  
  49. LayerObj            gBoardLayer;
  50. short                gClearSquare;
  51. extern CIconHandle    gPieceCIcon[26];
  52.  
  53. static OSErr    PieceLayerProc(LayerObj theLayer, short message);
  54. static OSErr    BoardLayerProc(LayerObj theLayer, short message);
  55. static void        PlotWithShadow(short x, short y);
  56.  
  57.  
  58.  
  59. /*****************************************************************************/
  60.  
  61.  
  62.  
  63. #pragma segment Config
  64. OSErr    InitOffscreen(void)
  65. {
  66.     RgnHandle    colorRgn;
  67.     short        depth;
  68.     OSErr        err;
  69.  
  70.     gClearSquare = 0;        /* Regular board imaging as default. */
  71.  
  72.     colorRgn = ScreenDepthRegion(8);
  73.     depth = (EmptyRgn(colorRgn)) ? 1 : 8;
  74.     DisposeRgn(colorRgn);
  75.  
  76.     err = NewLayer(&gBoardLayer, nil, BoardLayerProc, nil, depth, 0);
  77.         /* We create boardLayer at initialization time.  This layer will be
  78.         ** used to image the board off-screen.  Note that the layer has its own
  79.         ** layerProc.  The kLayerInit action doesn't call the default layerInit.
  80.         ** This custom layerProc uses just the size of the above GWorld to
  81.         ** determine the size of the bitmap it creates, so this layer isn't
  82.         ** necessarily the same depth as the above layer.  If there is no above
  83.         ** layer, then this custom layerProc needs to return paramErr for the
  84.         ** kLayerInit message, just as the default LayerProc does. */
  85.  
  86.     return(err);
  87. }
  88.  
  89.  
  90.  
  91. /*****************************************************************************/
  92.  
  93.  
  94.  
  95. #pragma segment Config
  96. void    MoveThePiece(FileRecHndl frHndl, short fromSq, Rect fromRect, Point fromLoc, Point *toLoc)
  97. {
  98.     WindowPtr        window, keepPort;
  99.     LayerObj        windowLayer, pieceLayer;
  100.     short            dx, dy, adx, ady, ticksForMove, tickDiff, update;
  101.     unsigned long    startTick;
  102.     Point            lastLoc, mouseLoc, pt;
  103.  
  104.     lastLoc.h = lastLoc.v = 0x4000;
  105.         /* Make sure that the first position gets updated.  We want a last mouse
  106.         ** location that is different than whatever the user would have clicked. */
  107.  
  108.     keepPort = SetFilePort(frHndl);
  109.     GetPort(&window);
  110.  
  111.     ImageDocument(frHndl, true);
  112.  
  113.     NewLayer(&windowLayer, nil, nil, window, 0, 0);
  114.         /* Create the layer object related to the window.  If NewLayer fails,
  115.         ** windowLayer is set to nil. */
  116.     (*windowLayer)->dstRect = BoardRect();
  117.         /* pieceLayer isn't the same size as the window's portRect.  By setting
  118.         ** windowLayer's dstRect, we change the area that the two layers map
  119.         ** to.  dstRect is set nil by NewLayer, and if it is left nil, then
  120.         ** the portRect is used for mapping.  Since we only want to map into
  121.         ** the window for the board, we set dstRect to just that portion of
  122.         ** the window. */
  123.     gClearSquare = fromSq;
  124.     gPiece       = (*frHndl)->doc.theBoard[fromSq];
  125.     ImageDocument(frHndl, true);
  126.     gClearSquare = 0;
  127.  
  128.     gTestRgn  = NewRgn();
  129.     gColorRgn = ScreenDepthRegion(8);        /* Screen of 8-bit or greater get color icon. */
  130.     pt.h = pt.v = 0;
  131.     GlobalToLocal(&pt);
  132.     OffsetRgn(gColorRgn, pt.h, pt.v);        /* Localize the area that gets color icons. */
  133.  
  134.     NewLayer(&pieceLayer, windowLayer, PieceLayerProc, nil, 0, 0);
  135.         /* pieceLayer is created, and it maps to the board area of windowLayer.
  136.         ** Note that windowLayer is a parameter for pieceLayer.  If windowLayer
  137.         ** failed to get created, then this call will return a paramErr.  This
  138.         ** is because if you don't state a port, pixmap, or bitmap, the default
  139.         ** layerProc (which PieceLayerProc calls) uses the above layer to
  140.         ** determine the size and depth of an off-screen GWorld it automatically
  141.         ** creates.  If there is also no above layer, then there is nothing that
  142.         ** can be used as a basis for the GWorld, and that results in a paramErr. */
  143.  
  144.     InsertLayer(gBoardLayer, windowLayer, 2);
  145.         /* Connect board layer in as the background layer. */
  146.     InvalLayer(windowLayer, fromRect, false);
  147.         /* On first update, redraw square where piece was picked up. */
  148.  
  149.     if (toLoc->h != 0x4000) {        /* If we have a start and end point, slide the piece. */
  150.         startTick = TickCount();
  151.         dx = adx = toLoc->h - fromLoc.h;
  152.         if (adx < 0) adx = -adx;
  153.         dy = ady = toLoc->v - fromLoc.v;
  154.         if (ady < 0) ady = -ady;
  155.         ticksForMove = (adx + ady) / 3;
  156.         if (ticksForMove > 30) ticksForMove = 30;
  157.             /* The piece slide will take at most half a second. */
  158.     }
  159.  
  160.     for (;;) {
  161.         if (toLoc->h == 0x4000) {        /* If user grabbed the piece, get where the mouse is now. */
  162.             GetMouse(&mouseLoc);
  163.             if (update = UpdateTime(frHndl, true)) DrawTime(frHndl);
  164.             if (update == 2) {
  165.                 if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kIsMove, nil);
  166.                 AlertIfGameOver(frHndl);
  167.                 lastLoc.h = lastLoc.v = 0x4000;
  168.                 break;
  169.             }
  170.         }
  171.         else {
  172.             tickDiff = TickCount() - startTick;
  173.             if (tickDiff > ticksForMove) tickDiff = ticksForMove;
  174.             mouseLoc.h = fromLoc.h + dx * tickDiff / ticksForMove;
  175.             mouseLoc.v = fromLoc.v + dy * tickDiff / ticksForMove;
  176.                 /* If sliding piece, calculate the new position, based on time. */
  177.         }
  178.         if ((lastLoc.h != mouseLoc.h) || (lastLoc.v != mouseLoc.v)) {
  179.                 /* If new piece position is different than last... */
  180.             lastLoc = mouseLoc;
  181.             gPieceRect = fromRect;
  182.             gPieceRect.right  += 5;            /* Make space for the piece's shadow. */
  183.             gPieceRect.bottom += 5;
  184.             OffsetRect(&gPieceRect, mouseLoc.h - fromLoc.h - 2, mouseLoc.v - fromLoc.v - 2);
  185.                 /* Position the update rect at the new mouse location but offset 2
  186.                 ** up and 2 left.  This offset is so the piece looks like it is
  187.                 ** lifted from the board for the first update. */
  188.             InvalLayer(windowLayer, gPieceRect, true);    /* Mark the area to be updated. */
  189.             UpdateLayer(windowLayer);                    /* DO IT. */
  190.         }
  191.         if (toLoc->h == 0x4000) {        /* If under user control... */
  192.             if (!StillDown()) break;    /* Break if mouse is released. */
  193.         }
  194.         else if (tickDiff == ticksForMove) break;
  195.             /* If piece being slid, break when it gets there. */
  196.     }
  197.  
  198.     DetachLayer(gBoardLayer);
  199.         /* Keep this permanent layer from being disposed of. */
  200.     DisposeThisAndBelowLayers(windowLayer);
  201.         /* Dispose of the layers and associated data. */
  202.     DisposeRgn(gColorRgn);
  203.     DisposeRgn(gTestRgn);
  204.  
  205.     SetPort(keepPort);
  206.     *toLoc = lastLoc;        /* Return where the piece was dropped. */
  207. }
  208.  
  209.  
  210.  
  211. /*****************************************************************************/
  212.  
  213.  
  214.  
  215. #pragma segment Config
  216. static OSErr    PieceLayerProc(LayerObj theLayer, short message)
  217. {
  218.     OSErr    err;
  219.     GrafPtr    thisPort;
  220.  
  221.     switch (message) {
  222.         case kLayerInit:
  223.             gCtab = nil;
  224.                 /* We will need a color table if the depth is greater than 1, and
  225.                 ** we succeed in creating the pixMap for the layer.  Assume that
  226.                 ** these conditions won't be met, and initialize the color table
  227.                 ** reference to nil. */
  228.             err = DefaultLayerProc(theLayer, kLayerInit);
  229.             if (!err) {
  230.                 thisPort = (*theLayer)->layerPort;
  231.                 gDepth = 1;
  232.                 if (thisPort->portBits.rowBytes & 0x8000)
  233.                     gDepth = (*(((CGrafPtr)thisPort)->portPixMap))->pixelSize;
  234.                 if (gDepth != 1) gCtab = GetCTable(64 + 8);
  235.                     /* We need a color table for the shadow if depth is greater than 1. */
  236.             }
  237.             break;
  238.         case kLayerDispose:
  239.             err = DefaultLayerProc(theLayer, kLayerDispose);
  240.                 /* Do the standard dispose behavior. */
  241.             if (gCtab) DisposeCTable(gCtab);
  242.                 /* Dispose of the color table for the piece shadow, if we have one. */
  243.             break;
  244.         case kLayerUpdate:
  245.             DefaultLayerProc(theLayer, kLayerUpdate);
  246.             SetLayerWorld(theLayer);
  247.             PlotWithShadow(gPieceRect.left, gPieceRect.top);
  248.                 /* Draw the piece and shadow into the piece layer in the new position. */
  249.             ResetLayerWorld(theLayer);
  250.             break;
  251.         default:
  252.             err = DefaultLayerProc(theLayer, message);
  253.                 /* For future messages, use the default behavior. */
  254.             break;
  255.     }
  256.  
  257.     return(err);
  258. }
  259.  
  260.  
  261.  
  262. /*****************************************************************************/
  263.  
  264.  
  265.  
  266. #pragma segment Config
  267. static OSErr    BoardLayerProc(LayerObj theLayer, short message)
  268. {
  269.     OSErr        err;
  270.     Rect        boardRect;
  271.     GWorldPtr    layerWorld;
  272.     CGrafPtr    keepPort;
  273.     GDHandle    keepGDevice;
  274.  
  275.     switch (message) {
  276.         case kLayerInit:
  277.             boardRect = BoardRect();
  278.             err = NewGWorld(&layerWorld, (*theLayer)->layerDepth, &boardRect, nil, nil, 0);
  279.             if (!err) {        /* If we succeeded at creating the GWorld... */
  280.                 (*theLayer)->layerOwnsPort = true;
  281.                 GetGWorld(&keepPort, &keepGDevice);        /* To get the GDevice. */
  282.                 (*theLayer)->layerPort    = (GrafPtr)layerWorld;
  283.                 (*theLayer)->layerGDevice = keepGDevice;
  284.                 SetLayerWorld(theLayer);
  285.                 SetOrigin(boardRect.left, boardRect.top);
  286.                 EraseRect(&boardRect);
  287.                     /* Pre-clear the bitmap before imaging into it. */
  288.                 ImageBoardLines(1, kBoardHOffset, kBoardVOffset);
  289.                     /* Pre-image the lines dividing the squares. */
  290.                 ResetLayerWorld(theLayer);
  291.             }
  292.             break;
  293.         default:
  294.             err = DefaultLayerProc(theLayer, message);
  295.                 /* Default behavior for everything else. */
  296.             break;
  297.     }
  298.  
  299.     return(err);
  300. }
  301.  
  302.  
  303.  
  304. /*****************************************************************************/
  305.  
  306.  
  307.  
  308. #pragma segment Config
  309. void    PlotWithShadow(short x, short y)
  310. {
  311.     GrafPtr        thePort;
  312.     Handle        shadowHndl;
  313.     short        pieceShadow;
  314.     ResType        iconType;
  315.     Rect        iconRect, destRect;
  316.     char        hstate;
  317.     PixMap        shadowPixMap;
  318.  
  319.     iconType = (gDepth == 1) ? 'ICON' : 'icl8';
  320.     if ((pieceShadow = gPiece) < 0) pieceShadow = -pieceShadow;
  321.     shadowHndl = GetResource(iconType, 400 + pieceShadow);
  322.     hstate = LockHandleHigh(shadowHndl);
  323.  
  324.     SetRect(&iconRect, 0, 0, 32, 32);
  325.     shadowPixMap.baseAddr   = *shadowHndl;
  326.     shadowPixMap.rowBytes   = (iconType == 'ICON') ? 4 : 0x8020;
  327.     shadowPixMap.bounds     = iconRect;
  328.     shadowPixMap.pmVersion  = 0;
  329.     shadowPixMap.packType   = 0;
  330.     shadowPixMap.packSize   = 0;
  331.     shadowPixMap.hRes       = 0x00480000;
  332.     shadowPixMap.vRes       = 0x00480000;
  333.     shadowPixMap.pixelType  = 0;
  334.     shadowPixMap.pixelSize  = 8;
  335.     shadowPixMap.cmpCount   = 1;
  336.     shadowPixMap.cmpSize    = 8;
  337.     shadowPixMap.planeBytes = 0;
  338.     shadowPixMap.pmTable    = gCtab;
  339.     shadowPixMap.pmReserved = 0;
  340.  
  341.     destRect.bottom = (destRect.top  = y + 5) + 32;
  342.     destRect.right  = (destRect.left = x + 5) + 32;
  343.         /* Add 5 to offset the shadow. */
  344.  
  345.     GetPort(&thePort);
  346.     CopyBits((BitMapPtr)&shadowPixMap, &(thePort->portBits), &iconRect, &destRect, srcOr, nil);
  347.     HSetState(shadowHndl, hstate);
  348.  
  349.     if (!gPieceCIcon[gPiece + KING])
  350.         gPieceCIcon[gPiece + KING] = ReadCIcon(gPiece + KING + 257);
  351.     if (!gPieceCIcon[gPiece + KING + 13])
  352.         gPieceCIcon[gPiece + KING + 13] = ReadCIcon(gPiece + KING + 13 + 257);
  353.  
  354.     OffsetRect(&destRect, -5, -5);
  355.         /* 5 was added for the shadow.  This undoes that. */
  356.  
  357.     if (!RectInRgn(&destRect, gColorRgn))        /* If 1-bit, draw b/w icon. */
  358.         DrawCIconByDepth(gPieceCIcon[gPiece + KING], destRect, 1, true);
  359.  
  360.     else {                                    /* Draw some combo of color and b/w icon. */
  361.         RectRgn(gTestRgn, &destRect);
  362.         SectRgn(gColorRgn, gTestRgn, gTestRgn);
  363.         if ((*gTestRgn)->rgnSize == 10) {
  364.             if (EqualRect(&((*gTestRgn)->rgnBBox), &destRect)) {        /* All color. */
  365.                 DrawCIconByDepth(gPieceCIcon[gPiece + KING + 13], destRect, 8, true);
  366.                 return;
  367.             }
  368.         }
  369.         SetClip(gTestRgn);
  370.         DrawCIconByDepth(gPieceCIcon[gPiece + KING + 13], destRect, 8, true);    /* Color part. */
  371.         RectRgn(gTestRgn, &destRect);
  372.         XorRgn(gColorRgn, gTestRgn, gTestRgn);
  373.         SetClip(gTestRgn);
  374.         DrawCIconByDepth(gPieceCIcon[gPiece + KING], destRect, 1, true);        /* b/w part. */
  375.         SetRectRgn(gTestRgn, -32000, -32000, 32000, 32000);
  376.         SetClip(gTestRgn);
  377.     }
  378. }
  379.  
  380.  
  381.  
  382.